﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.IO;

namespace easyServer
{
    public partial class Form1 : Form
    {
        TcpListener serverSocket;
        bool isListening = false;

        public Form1()
        {
            InitializeComponent();
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            try
            {
                String folder = textFolder.Text.Trim();
                if (folder.Length == 0 || Directory.Exists(folder) == false)
                {
                    labelStatus.Text = "Status: Invalid folder!";
                }
                else
                {
                    textFolder.Enabled = false;
                    textServerIP.Enabled = false;
                    textServerPort.Enabled = false;
                    buttonBrowse.Enabled = false;    
                    IPAddress address = IPAddress.Parse(textServerIP.Text);
                    int port = int.Parse(textServerPort.Text);
                    serverSocket = new TcpListener(address, port);
                    serverSocket.Start();
                    labelStatus.Text = "Status: Server is listening!";
                    isListening = true;

                    Thread threadListening = new Thread(new ThreadStart(ListeningClient));
                    threadListening.Start();

                    buttonStop.Enabled = true;
                    buttonStart.Enabled = false;
                }
            }
            catch (FormatException)
            {
                labelStatus.Text = "Status: Invalid IP or Port";
                textFolder.Enabled = true;
                textServerIP.Enabled = true;
                textServerPort.Enabled = true;
                buttonBrowse.Enabled = true;
            }
        }

        private void ListeningClient()
        {
            try
            {
                while (isListening)
                {
                    TcpClient clientSocket = default(TcpClient);
                    clientSocket = serverSocket.AcceptTcpClient();
                    
                    MethodInvoker action = delegate
                        { labelStatus.Text = "Client connected!"; };
                    labelStatus.BeginInvoke(action);

                    int bufferSize = clientSocket.ReceiveBufferSize;

                    NetworkStream networkStream = clientSocket.GetStream();
                    byte[] bytesFrom = new byte[bufferSize];
                    int ret = networkStream.Read(bytesFrom, 0, bufferSize);
                    string filename = string.Empty;
                    string dataFromClient = System.Text.Encoding.UTF8.GetString(bytesFrom);

                    if (dataFromClient.Substring(0, 6).Equals("upload"))
                    {
                        action = delegate { labelStatus.Text = "Receiving!"; };
                        labelStatus.BeginInvoke(action);

                        filename = dataFromClient.Substring(7, dataFromClient.IndexOf('\0') - 7) + ".mp3";
                        Byte[] sendBytes = Encoding.ASCII.GetBytes("OK");   // Send OK
                        networkStream.Write(sendBytes, 0, 2);

                        action = delegate { listBox.Items.Add(filename); };
                        listBox.BeginInvoke(action);

                        ret = networkStream.Read(bytesFrom, 0, bufferSize);
                        long fileLength = BitConverter.ToInt64(bytesFrom, 0);
                        long offset = 0;
                        string filePath;
                        if (textFolder.Text.Equals(""))
                            filePath = filename;
                        else
                            filePath = textFolder.Text + "\\" + filename;
                        
                        if (File.Exists(filePath)) 
                        {
                            File.Delete(filePath);
                        }

                        FileStream fs = new FileStream(filePath, FileMode.CreateNew);
                        BinaryWriter w = new BinaryWriter(fs);
                        long percent;

                        DateTime now = DateTime.Now;
                        String dtFormat = @"M/d/yyyy hh:mm";
                        String dtString = "[" + DateTime.Now.ToString(dtFormat) + "] ";

                        while ((offset < fileLength))
                        {
                            percent  = offset * 100 / fileLength;
                            action = delegate { listBox.Items[listBox.Items.Count - 1] = dtString + filename + " (" + percent.ToString() + "%)"; };
                            listBox.BeginInvoke(action);

                            ret = networkStream.Read(bytesFrom, 0, bufferSize);
                            w.Write(bytesFrom, 0, ret);
                            offset += ret;
                        }

                        percent = fileLength * 100 / fileLength;
                        action = delegate { listBox.Items[listBox.Items.Count - 1] = dtString + filename + " (" + percent.ToString() + "%)"; };
                        listBox.BeginInvoke(action);
                        w.Flush();
                        w.Close();
                        fs.Close();
                    }

                    action = delegate { labelStatus.Text = "Successed! "; };
                    labelStatus.BeginInvoke(action);

                    networkStream.Flush();
                    clientSocket.Close();
                }
            }
            catch { }
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            textFolder.Enabled = true;
            textServerIP.Enabled = true;
            textServerPort.Enabled = true;

            isListening = false;
            serverSocket.Stop();
            labelStatus.Text = "Server is stopped!";

            buttonStart.Enabled = true;
            buttonStop.Enabled = false;
        }

        private void buttonBrowse_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
            {
                textFolder.Text = folderBrowserDialog.SelectedPath;
            }
        }

        private void clearListToolStripMenuItem_Click(object sender, EventArgs e)
        {
            listBox.Items.Clear();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            if (Properties.Settings.Default.ipaddress.Equals(string.Empty))
            {
                String strHostName = Dns.GetHostName();
                IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);
                IPAddress[] addr = ipEntry.AddressList;
                for (int i = 0; i < addr.Length; i++)
                    if (addr[i].AddressFamily == AddressFamily.InterNetwork)
                        textServerIP.Text = addr[i].ToString();
            }
            else
            {
                textServerIP.Text = Properties.Settings.Default.ipaddress;
                textServerPort.Text = Properties.Settings.Default.port;
                textFolder.Text = Properties.Settings.Default.folder;
            }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (isListening)
            {
                isListening = false;
                serverSocket.Stop();
            }

            Properties.Settings.Default.ipaddress = textServerIP.Text;
            Properties.Settings.Default.port = textServerPort.Text;
            Properties.Settings.Default.folder = textFolder.Text;
            Properties.Settings.Default.Save();
        }

        
    }
}
